//
//  UIListView.h
//  Vgo
//
//  Created by 21CN Vgo on 11-4-6.
//  Copyright 2011 __MyCompanyName__. All rights reserved.
//

#import <UIKit/UIKit.h>
#import "UIListViewCell.h"

@class UIListView;
@class UIListViewCell;
@class CellRange;

typedef enum {
    UIListViewScrollPositionNone,        
    UIListViewScrollPositionTopLeft,    
    UIListViewScrollPositionMiddle,   
    UIListViewScrollPositionBottomRight
} UIListViewScrollPosition;            // scroll so row of interest is completely visible at top/center/bottom of view

@protocol UIListViewDataSource <NSObject>
 
@required

- (NSInteger)numberOfColumnsInListView:(UIListView *)listView;
- (NSInteger)numberOfRowsInListView:(UIListView *)listView;
- (NSInteger)numberOfCellsInListView:(UIListView *)listView;
- (UIListViewCell *)listView:(UIListView *)listView cellAtIndexPath:(NSIndexPath *)indexPath;
- (void)listView:(UIListView *)listView commitEditingStyle:(UIListViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath;

@end
 

@protocol UIListViewDelegate <NSObject>

@optional

// Display customization

- (void)listView:(UIListView *)listView willDisplayCell:(UIListViewCell *)cell atIndexPath:(NSIndexPath *)indexPath;

// Variable height or width support

- (CGFloat)listView:(UIListView *)listView heightForRow:(NSInteger)row;
- (CGFloat)listView:(UIListView *)listView widthForColumn:(NSInteger)column;

// Selection

// Called before the user changes the selection. Return a new indexPath, or nil, to change the proposed selection.
- (NSIndexPath *)listView:(UIListView *)listView willSelectCellAtIndexPath:(NSIndexPath *)indexPath;
- (NSIndexPath *)listView:(UIListView *)listView willDeselectCellAtIndexPath:(NSIndexPath *)indexPath;
// Called after the user changes the selection.
- (void)listView:(UIListView *)listView didSelectCellAtIndexPath:(NSIndexPath *)indexPath;
- (void)listView:(UIListView *)listView didDeselectCellAtIndexPath:(NSIndexPath *)indexPath;

// Moving/reordering

// Allows customization of the target row for a particular row as it is being moved/reordered
- (NSIndexPath *)listView:(UIListView *)listView targetIndexPathForMoveFromIndexPath:(NSIndexPath *)sourceIndexPath toProposedIndexPath:(NSIndexPath *)proposedDestinationIndexPath;     

// editing style
- (void)willChangeEditing:(BOOL)editing listView:(UIListView *)listView;

@end


@interface UIListView : UIScrollView <NSCoding, UIScrollViewDelegate> {
@private
	id <UIListViewDataSource>		_dataSource;
	id <UIListViewDelegate>			_listViewDelegate;
	id <UIScrollViewDelegate>		_outsideDelegate;
	CGFloat							_rowHeight;
	CGFloat							_columnWidth;
	UIView *						_backgroundView;
	
	BOOL							_allowsSelection;
	BOOL							_allowsMultiSelection;
	BOOL							_allowsLongPressAnimation;
	BOOL							_allowsPanGuestureEdit;
	NSNumber						*_singleEditingIndex;
	BOOL							_editing;
	BOOL							_animating;
	
	NSMutableDictionary        *_reusableTableCells;
	NSMutableDictionary        *_visibleCells;
	
	NSInteger					_numberOfRows;
	NSInteger					_numberOfColumns;
	NSInteger					_numberOfCells;
	
	NSMutableArray			   *_rowEdges;
	NSMutableArray			   *_colEdges;	
	
	BOOL						_shoudRelayout;
	
    NSMutableArray             *_selectedIndexes;
	//NSInteger                   _swipeToDeleteSection;
	//NSInteger                   _swipeToDeleteRow;
    NSNumber                   *_pendingSelectionIndex;
    NSArray                    *_pendingDeselectionIndexes;
	NSUInteger				   _latestSelectRow;
	NSUInteger				   _latestSelectColum;
	// UIView                     *_touchedContentView;
	// UIView                     *_newContentView;
	
	NSInteger                  _updateCount;	
	NSMutableArray			   *_removeCells;
	NSMutableArray			   *_removeCellsAnimated;
	NSMutableArray			   *_insertItems;
	NSMutableArray			   *_reloadItems;
	NSMutableArray			   *_insertItemsAnimated;
	
	NSMutableArray			   *_changeItemOriginalPositions;
	NSMutableArray			   *_itemOperations;	

	BOOL					   _longPress;
	
	NSString				   *_delImageName;
	NSMutableArray			   *_deleteButtons;
	
	CellRange				   *_visRange;
	
	UIEdgeInsets			   _scrollInset;
}


- (id)initWithFrame:(CGRect)frame;

@property(nonatomic,assign)   id <UIListViewDataSource>		dataSource;
@property(nonatomic,assign)   id <UIListViewDelegate>		listViewDelegate;
@property(nonatomic)          CGFloat						rowHeight;             // will return the default value if unset
@property(nonatomic)          CGFloat						columnWidth;           // will return the default value if unset

@property(nonatomic, readwrite, retain) UIView *backgroundView __OSX_AVAILABLE_STARTING(__MAC_NA,__IPHONE_3_2); // the background view will be automatically resized to track the size of the list view.  this will be placed as a subview of the list view behind all cells.  default may be non-nil for some devices.

@property(nonatomic, retain) NSString *delImageName;
@property(nonatomic, assign) BOOL allowsMultiSelection;

@property(nonatomic, assign) UIEdgeInsets scrollInset;

// Data

- (void)reloadData;                 // reloads everything from scratch. redisplays visible rows. because we only keep info about visible rows, this is cheap. will adjust offset if list shrinks

// Info

- (NSInteger)numberOfColumns;
- (NSInteger)numberOfRows;

- (CGRect)rectForCellAtIndexPath:(NSIndexPath *)indexPath;

- (NSIndexPath *)indexPathForCellAtPoint:(CGPoint)point;                       // returns nil if point is outside list
- (NSIndexPath *)indexPathForCell:(UIListViewCell *)cell;                      // returns nil if cell is not visible
- (NSArray *)indexPathsForCellsInRect:(CGRect)rect;                            // returns nil if rect not valid 

- (UIListViewCell *)cellAtIndexPath:(NSIndexPath *)indexPath;            // returns nil if cell is not visible or index path is out of range
- (NSArray *)visibleCells;
- (NSArray *)indexPathsForVisibleCells;

- (void)scrollToCellAtIndexPath:(NSIndexPath *)indexPath atScrollPosition:(UIListViewScrollPosition)scrollPosition animated:(BOOL)animated;
- (void)scrollToNearestSelectedCellAtScrollPosition:(UIListViewScrollPosition)scrollPosition animated:(BOOL)animated;

// Row insertion/deletion/reloading.

- (void)beginUpdates;   // allow multiple insert/delete of rows and sections to be animated simultaneously. Nestable
- (void)endUpdates;     // only call insert/delete/reload calls or change the editing state inside an update block.  otherwise things like row count, etc. may be invalid.

- (void)insertCells:(NSIndexSet *)cells withCellAnimated:(BOOL)animated;
- (void)deleteCells:(NSIndexSet *)cells withCellAnimated:(BOOL)animated;
- (void)reloadCells:(NSIndexSet *)cells withCellAnimated:(BOOL)animated; 

@property(nonatomic) BOOL allowsSelection;  // default is YES.
@property(nonatomic) BOOL allowsLongPressAnimation;
@property(nonatomic) BOOL allowsPanGuestureEdit;

// Editing. When set, rows show delete/reorder controls

@property(nonatomic,getter=isEditing) BOOL editing;                             // default is NO. setting is not animated.
- (void)setEditing:(BOOL)editing animated:(BOOL)animated;

// Selection

- (NSIndexPath *)indexPathForSelectedCell;                                       // return nil or index path representing cell of selection.
- (NSArray *)indexPathForSelectedCells;

// Selects and deselects a cell. These methods will not call the delegate methods (-listView:willSelectCellAtIndexPath: or listView:didSelectCellAtIndexPath:), nor will it send out a notification.
- (void)selectCellAtIndexPath:(NSIndexPath *)indexPath animated:(BOOL)animated scrollPosition:(UIListViewScrollPosition)scrollPosition;
- (void)deselectCellAtIndexPath:(NSIndexPath *)indexPath animated:(BOOL)animated;

- (UIListViewCell *)dequeueReusableCellWithIdentifier:(NSString *)identifier;  // Used by the delegate to acquire an already allocated cell, in lieu of allocating a new one.

@end

//_______________________________________________________________________________________________________________

// This category provides convenience methods to make it easier to use an NSIndexPath to represent a column and row
@interface NSIndexPath (UIListView)

+ (NSIndexPath *)indexPathForRow:(NSUInteger)row inColumn:(NSUInteger)column;

@property(nonatomic,readonly) NSUInteger column;

@end

@interface ItemPosition : NSObject {
	NSUInteger _index;
	CGRect _oriRect;
	NSUInteger _oriIndex;
}

@property(nonatomic, assign) NSUInteger index;
@property(nonatomic, assign) CGRect oriRect;
@property(nonatomic, assign) NSUInteger oriIndex;

- (id)initWithIndex:(NSUInteger)theIndex oriRect:(CGRect)theRect oriIndex:(NSUInteger)theOriIndex;

@end

typedef enum {
	OpTypeUnknow = 0,
	OpTypeInsert = 1,
	OpTypeDelete = 2,
	OpTypeUpdate = 3
}OperationType;

@interface ItemOperation : NSObject {
	OperationType _type;
	NSIndexSet *_indexSet;
	BOOL _animated;
}

@property(nonatomic, assign) OperationType type;
@property(nonatomic, retain) NSIndexSet * indexSet;
@property(nonatomic, assign) BOOL animated;

- (id)initWithType:(OperationType)theType indexSet:(NSIndexSet *)theIndexSet animated:(BOOL)animatedFlag;

@end

@interface ItemInfo : NSObject {
	BOOL _newFlag;
	NSInteger _step;
	NSUInteger _oriIndex;
}

@property(nonatomic, assign) BOOL newFlag;
@property(nonatomic, assign) NSInteger step;
@property(nonatomic, assign) NSUInteger oriIndex;

- (id)initWithOriIndex:(NSUInteger)theIndex step:(NSInteger)theStep flag:(BOOL)theNewFlag;

@end

@interface CellRange : NSObject
{
	NSUInteger _left;
	NSUInteger _top;
	NSUInteger _right;
	NSUInteger _bottom;
}

@property(nonatomic, assign) NSUInteger left;
@property(nonatomic, assign) NSUInteger top;
@property(nonatomic, assign) NSUInteger right;
@property(nonatomic, assign) NSUInteger bottom;

- (id)initWithLeft:(NSUInteger)theLeft top:(NSUInteger)theTop right:(NSUInteger)theRight bottom:(NSUInteger)theBottom;
- (void)setRange:(CellRange *)range;

@end





